import * as Cesium from 'cesium'
import * as turf from '@turf/turf'
import * as echarts from 'echarts'

export default class ProfileAnalyse {
  chart
  handler
  listener
  constructor(viewer, div) {
    this.viewer = viewer
    this.startAndEndPoints = []    // 一条线的第一个点和最后一个点
    this.tempEntities = new Cesium.EntityCollection()    // 要素集合
    this.div = div   // 按钮元素
    this.interNumber = 5000    // 一条线上的插值数量，类似于微分

  }
  // 绘制点
  drawPoint(position) {
    let point = this.viewer.entities.add({
      name: '点几何对象',
      position: position,
      point: {
        color: Cesium.Color.SKYBLUE,
        pixelSize: 10,
        outlineColor: Cesium.Color.YELLOW,
        outlineWidth: 3,
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
        heightReference: Cesium.HeightReference.CLAMP_TO_GROUND
      }
    })
    this.tempEntities.add(point)
    return point
  }
  // 绘制线
  drawPolyline(positions) {
    if (positions.length < 1) return
    let line = this.viewer.entities.add({
      name: "线几何对象",
      polyline: {
        positions: positions,
        width: 5.0,
        material: new Cesium.PolylineGlowMaterialProperty({
          color: Cesium.Color.GOLD,
        }),
        depthFailMaterial: new Cesium.PolylineGlowMaterialProperty({
          color: Cesium.Color.GOLD,
        })
      }
    })
    this.tempEntities.add(line)
    return line
  }
  // 计算高程值
  getTerrainHeight(lon, lat) {
    // 角度转弧度计算高程值
    let terrainHeight = this.viewer.scene.globe.getHeight(Cesium.Cartographic.fromDegrees(lon, lat))
    terrainHeight = (terrainHeight !== undefined) ? terrainHeight : 0
    return {
      lon: lon,
      lat: lat,
      height: terrainHeight
    }
  }
  // 计算距离
  getDistance(point1, point2) {
    // 根据经纬度计算距离
    let start = Cesium.Cartographic.fromDegrees(point1.lon, point1.lat, point1.height)
    let end = Cesium.Cartographic.fromDegrees(point2.lon, point2.lat, point2.height)
    let geodesic = new Cesium.EllipsoidGeodesic()
    geodesic.setEndPoints(start, end)
    // 计算出两点经纬度之间的距离
    let s = geodesic.surfaceDistance
    // 计算出两点包括高度之间的距离，并将米换算为千米
    s = Math.sqrt(Math.pow(s, 2) + Math.pow(end.height - start.height, 2)) / 1000
    return s
  }
  // 添加echart折线图
  initChart(profile) {
    this.chart = document.createElement('div')
    this.chart.style.width = 450 + 'px'
    this.chart.style.height = 300 + 'px'
    this.chart.style.position = 'absolute'
    this.chart.style.left = 100 + 'px'
    this.chart.style.bottom = 50 + 'px'
    this.chart.style.zIndex = 100
    this.viewer.canvas.parentElement.appendChild(this.chart)
    var myChart = echarts.init(this.chart)
    // 绘制图表
    myChart.setOption({
      tooltip: {},
      xAxis: {
        name: '距离(km)',
        data: profile.arrLX,
        axisLine: {
          lineStyle: {
            color: 'white'
          }
        }
      },
      yAxis: {
        name: '高程值(m)',
        axisLine: {
          lineStyle: {
            color: 'white'
          }
        }
      },
      series: [
        {
          type: 'line',
          data: profile.arrHB,
          areaStyle: {}
        }
      ]
    })
  }
  // 添加剖面分析
  addProfileAnalysis() {
    const that = this
    // 移除默认双击事件trackedEntity
    that.viewer.cesiumWidget.screenSpaceEventHandler.removeInputAction(Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK)
    // 开启深度检测
    that.viewer.scene.globe.depthTestAgainstTerrain = true
    that.listener = () => {
      let tempPoints = []    // 放置添加线时点的坐标数组
      let point = that.viewer.entities.add({
        point: {
          color: Cesium.Color.SKYBLUE,
          pixelSize: 10,
          outlineColor: Cesium.Color.YELLOW,
          outlineWidth: 3,
          disableDepthTestDistance: Number.POSITIVE_INFINITY
        }
      })
      that.handler = new Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas)
      that.handler.setInputAction(function (movement) {
        let position = that.viewer.camera.pickEllipsoid(movement.endPosition, that.viewer.scene.globe.ellipsoid)
        point.position = position
      }, Cesium.ScreenSpaceEventType.MOUSE_MOVE)
      that.handler
      that.handler.setInputAction(function (movement) {
        // 不加载地形时使用，得到的是Cartesian2二维坐标
        let position = that.viewer.camera.pickEllipsoid(movement.position, that.viewer.scene.globe.ellipsoid)
        // 加载地形时使用，得到的是Cartesian3三维坐标
        let cartesian = that.viewer.scene.globe.pick(
          that.viewer.camera.getPickRay(movement.position),
          that.viewer.scene
        )
        // 笛卡尔转WGS84角度
        let lon = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cartesian).longitude)
        let lat = Cesium.Math.toDegrees(Cesium.Cartographic.fromCartesian(cartesian).latitude)
        that.startAndEndPoints.push([lon, lat])
        that.drawPoint(cartesian)
        tempPoints.push(cartesian)
        //调用绘制点的接口
        if (tempPoints.length > 1) {
          that.viewer.entities.remove(point)   // 当绘制第二个点时，需要把移动事件那个点在图上删除。
          that.drawPolyline([tempPoints.at(-2), tempPoints.at(-1)])
        }
        if (that.startAndEndPoints.length === 2) {
          that.handler.destroy()
          that.handler = null
          let profile = {
            points: [],    // 添加有高程值的插值点
            arrLX: [],     // 添加每一个插值点到初始点的距离
            arrHB: [],     // 添加每一个插值点的高程
            distance: 0   // 添加总距离
          }
          profile.arrLX.push(0)    // 第一个数是初始点到初始点的距离，所以是0
          let line = turf.lineString(that.startAndEndPoints)
          let length = turf.length(line)
          for (let i = 0; i < that.interNumber; i++) {
            let point = turf.along(line, i * length / that.interNumber)
            point = that.getTerrainHeight(point.geometry.coordinates[0], point.geometry.coordinates[1])
            profile.points.push(point)
            profile.arrHB.push(point.height)
            // that.drawPoint(Cesium.Cartesian3.fromDegrees(point.lon, point.lat, point.height))
          }
          // 循环计算每一段的距离，并放到arrLX中，并计算总距离
          for (let i = 1; i < profile.points.length - 1; i++) {
            let disc = that.getDistance(profile.points[i - 1], profile.points[i])
            profile.distance += disc
            profile.arrLX.push(profile.arrLX[i - 1] + disc)
          }
          that.initChart(profile)
        }
      }, Cesium.ScreenSpaceEventType.LEFT_CLICK)
    }
    that.div.addEventListener('click', that.listener)
  }
  // 删除剖面分析
  removeProfileAnalysis() {
    this.viewer.entities.removeAll()
    this.tempEntities.removeAll()
    this.startAndEndPoints.length = 0
    if (this.chart) {
      this.viewer.canvas.parentElement.removeChild(this.chart)
      this.chart = null
    }
    this.div.removeEventListener('click', this.listener)
    this.listener = null
  }
}